﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Serilog;
using Swashbuckle.AspNetCore.Filters;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Claims;
using System.Text;
using AutoMapper;
using XinLife.Model;
using XinLife.Core.Helper;
using StackExchange.Profiling;
using Serilog.Events;
using XinLife.Core;
#nullable disable
namespace XinLife.Common
{
    public static class StartupUtil
    {
        public static void RegisterAssemblyTypes(this IServiceCollection serviceCollection, Assembly assembly, string endWith)
        {
            var types = assembly.GetTypes().Where(x => x.IsClass && !x.IsAbstract);
            if (!string.IsNullOrEmpty(endWith))
            {
                types = types.Where(x => x.Name.EndsWith(endWith));
            }
            var interfaces = assembly.GetTypes().Where(w => w.IsInterface);
            if (!string.IsNullOrEmpty(endWith))
            {
                interfaces = interfaces.Where(x => x.Name.EndsWith(endWith));
            }
            var interfaceArray = interfaces as Type[] ?? interfaces.ToArray();
            foreach (var type in types)
            {
                var interfaceType = interfaceArray.FirstOrDefault(w => w.IsAssignableFrom(type));
                if (interfaceType != null)
                {
                    serviceCollection.AddScoped(interfaceType, type);
                }
            }
        }

        /// <summary>
        /// 添加日志
        /// </summary>
        /// <param name="builder"></param>
        public static void AddSerilog(this WebApplicationBuilder builder)
        {
            string LogFilePath(string LogEvent) => $@"{Directory.GetCurrentDirectory()}/logs/{LogEvent}/log.log";
            // 存储日志文件的格式
            string OutputTemplate = "Date：{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}{SourceContext} {ThreadId}{NewLine}LogLevel：{Level}{NewLine}Message：{Message}{NewLine}{Exception}" + new string('-', 50) + "{NewLine}{NewLine}";

            builder.Host.UseSerilog((context, logger) =>
            {
                logger.Enrich.FromLogContext()
                 .ReadFrom.Configuration(context.Configuration)
                 .WriteTo.Console()
                 .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
                 .MinimumLevel.Override("System.Net.Http.HttpClient.HttpMessageHandler", LogEventLevel.Warning)
                 .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Information).WriteTo.File(LogFilePath("Information"), rollingInterval: RollingInterval.Day, outputTemplate: OutputTemplate))
                 .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning).WriteTo.File(LogFilePath("Warning"), rollingInterval: RollingInterval.Day, outputTemplate: OutputTemplate))
                 .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Error).WriteTo.File(LogFilePath("Error"), rollingInterval: RollingInterval.Day, outputTemplate: OutputTemplate))
                  .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Debug).WriteTo.File(LogFilePath("Debug"), rollingInterval: RollingInterval.Day, outputTemplate: OutputTemplate))
                  .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly((p) => //http请求日志单独保存
                  {
                      ScalarValue scalar = new ScalarValue(AppLogEvents.HTTP.Id);
                      if (p.Properties.TryGetValue("EventId", out LogEventPropertyValue propertyValue))
                      {
                          var stValue = propertyValue as StructureValue;
                          if (stValue != null) return stValue.Properties.Any(cc => scalar.Equals(cc.Value));
                      }
                      return false;
                  }).WriteTo.File(LogFilePath(AppLogEvents.HTTP.ToString()), rollingInterval: RollingInterval.Day, outputTemplate: OutputTemplate));
            });
        }
        
    }
}
